From d254fd93441175da2b6e3073ff77a1c89bf3f44c Mon Sep 17 00:00:00 2001 From: robertl Date: Thu, 13 Jul 2006 05:33:37 +0000 Subject: [PATCH] Olaf eliminates a zillion hardcoded staticly sized buffers and commonizes our ASCII text reader into the new 'textfile' scheme. --- Makefile.in | 2 +- arcdist.c | 12 ++--- compegps.c | 11 +++-- configure.in | 2 +- cst.c | 15 ++++-- csv_util.c | 15 +++--- defs.h | 22 +++++++++ garmin_txt.c | 7 ++- google.c | 3 -- gpsutil.c | 16 ++++--- hsa_ndv.c | 2 +- igc.c | 37 +++++++-------- inifile.c | 25 ++++------ netstumbler.c | 13 ++++-- nmea.c | 10 ++-- nmn4.c | 26 ++++------- ozi.c | 14 +++--- pcx.c | 9 ++-- polygon.c | 13 ++---- stmwpp.c | 13 ++++-- textfile.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ tiger.c | 10 ++-- tmpro.c | 16 ++++--- unicsv.c | 24 ++++++---- xcsv.c | 14 +++--- 25 files changed, 307 insertions(+), 148 deletions(-) create mode 100644 textfile.c diff --git a/Makefile.in b/Makefile.in index 726c881eb..b2489749e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,7 +73,7 @@ SHAPE=shapelib/shpopen.o shapelib/dbfopen.o LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o \ csv_util.o strptime.o grtcirc.o vmem.o util_crc.o xmlgeneric.o \ uuid.o formspec.o xmltag.o cet.o cet_util.o fatal.o rgbcolors.o \ - inifile.o garmin_fs.o gbsleep.o units.o @GBSER@ \ + inifile.o garmin_fs.o gbsleep.o units.o textfile.o @GBSER@ \ $(COLDSYNC) $(GARMIN) $(JEEPS) $(SHAPE) $(FMTS) $(FILTERS) OBJS = main.o globals.o $(LIBOBJS) diff --git a/arcdist.c b/arcdist.c index e0379f42e..c173c7ca5 100644 --- a/arcdist.c +++ b/arcdist.c @@ -59,17 +59,16 @@ arcdist_process(void) extra_data *ed; double lat1, lon1, lat2, lon2; int fileline = 0; + char *line; + textfile_t *tin; - FILE *arcfile = xfopen( arcfileopt, "r", MYNAME ); + tin = textfile_open_read(arcfileopt, MYNAME ); lat1 = lon1 = lat2 = lon2 = BADVAL; - while ( !feof(arcfile)) { - char line[200]; + while ((line = textfile_read(tin))) { char *pound = NULL; int argsfound = 0; - fgets( line, sizeof(line), arcfile ); - fileline++; pound = strchr( line, '#' ); @@ -124,8 +123,7 @@ arcdist_process(void) lon1 = lon2; } - fclose(arcfile); - + textfile_done(tin); QUEUE_FOR_EACH(&waypt_head, elem, tmp) { waypoint *wp = (waypoint *) elem; diff --git a/compegps.c b/compegps.c index 404230a66..1e41df8cc 100644 --- a/compegps.c +++ b/compegps.c @@ -318,7 +318,7 @@ static void compegps_rd_init(const char *fname) { fin_name = (char *)fname; - fin = xfopen(fname, "r", MYNAME); + fin = xfopen(fname, "rb", MYNAME); } static void @@ -330,13 +330,15 @@ compegps_rd_deinit(void) static void compegps_data_read(void) { - char buff[1024]; + textfile_t *tin; + char *buff; int line = 0; waypoint *wpt = NULL; route_head *route = NULL; route_head *track = NULL; - while (NULL != fgets(buff, sizeof(buff), fin)) + tin = textfile_init(fin); + while ((buff = textfile_read(tin))) { char *cin = buff; char *ctail, *cx; @@ -405,7 +407,8 @@ compegps_data_read(void) parse_track_info(ctail, track); break; } - } + } + textfile_done(tin); } /* ----------------------------------------------------------- */ diff --git a/configure.in b/configure.in index 6bfd7f0e9..65adeb687 100644 --- a/configure.in +++ b/configure.in @@ -67,7 +67,7 @@ AC_ARG_ENABLE(csv, AC_MSG_RESULT(no) fi -AC_MSG_CHECKING(whether to support csv formats) +AC_MSG_CHECKING(whether to support filters) AC_ARG_ENABLE(filters, [ --enable-filters=[(yes)|no]], [ enable_filters="$enableval"],[enable_filters="yes"]) diff --git a/cst.c b/cst.c index d2b58863d..8528d3b5a 100644 --- a/cst.c +++ b/cst.c @@ -140,7 +140,7 @@ static void cst_rd_init(const char *fname) { fin_name = xstrdup(fname); - fin = xfopen(fname, "r", MYNAME); + fin = xfopen(fname, "rb", MYNAME); temp_route = NULL; } @@ -157,7 +157,7 @@ cst_rd_deinit(void) static void cst_data_read(void) { - char buff[1024]; + char *buff; int line = 0; int data_lines = -1; int line_of_count = -1; @@ -167,9 +167,11 @@ cst_data_read(void) int cst_points = -1; route_head *track = NULL; waypoint *wpt = NULL; + textfile_t *tin; + tin = textfile_init(fin); - while (NULL != fgets(buff, sizeof(buff), fin)) + while ((buff = textfile_read(tin))) { char *cin = buff; @@ -214,14 +216,15 @@ cst_data_read(void) wpt->url = cst_make_url(cin); } - while (NULL != fgets(buff, sizeof(buff), fin)) + while ((buff = textfile_read(tin))) { line++; cin = lrtrim(buff); if (strcmp(cin + 2, "note") == 0) { - fgets(buff, sizeof(buff), fin); + buff = textfile_read(tin); + if (buff == NULL) buff = ""; line++; cin = lrtrim(buff); if (*cin != '\0') @@ -315,6 +318,8 @@ cst_data_read(void) if ((cst_points >= 0) && (data_lines != cst_points)) warning(MYNAME ": Loaded %d point(s), but line %d says %d!\n", data_lines, line_of_count, cst_points); + + textfile_done(tin); } #if 0 diff --git a/csv_util.c b/csv_util.c index c485a3f8a..fdb14b7e9 100644 --- a/csv_util.c +++ b/csv_util.c @@ -994,20 +994,20 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) void xcsv_data_read(void) { - char buff[8192]; + char *buff; char *s; waypoint *wpt_tmp; int linecount = 0; queue *elem, *tmp; field_map_t *fmp; ogue_t *ogp; + textfile_t *tin; + + tin = textfile_init(xcsv_file.xcsvfp); - do { + while ((buff = textfile_read(tin))) { linecount++; - memset(buff, '\0', sizeof(buff)); - fgets(buff, sizeof(buff), xcsv_file.xcsvfp); - - rtrim(buff); + buff = lrtrim(buff); /* skip over x many lines on the top for the prologue... */ if ((xcsv_file.prologue_lines) && ((linecount - 1) < @@ -1060,7 +1060,8 @@ xcsv_data_read(void) waypt_add(wpt_tmp); } - } while (!feof(xcsv_file.xcsvfp)); + } + textfile_done(tin); } static void diff --git a/defs.h b/defs.h index a9a6073e3..30487f504 100644 --- a/defs.h +++ b/defs.h @@ -796,4 +796,26 @@ int color_to_bbggrr(char *cname); */ #define unknown_alt -99999999.0 +/* + * textfile: buffered OS independent (CRLF,NL,CR) text reader + */ + +typedef struct +{ + FILE *file_in; + char buf[1024]; + char *buf_pos; + char *buf_end; + char *line; + int line_size; + int line_no; + unsigned char tfclose:1; +} textfile_t; + +textfile_t *textfile_init(const FILE *file_in); +textfile_t *textfile_open_read(const char *filename, const char *module); +void textfile_done(textfile_t *tf); +char *textfile_read(textfile_t *tf); +int textfile_getc(textfile_t *tf); + #endif /* gpsbabel_defs_h_included */ diff --git a/garmin_txt.c b/garmin_txt.c index 9709e85b2..52d50efcd 100644 --- a/garmin_txt.c +++ b/garmin_txt.c @@ -1224,11 +1224,13 @@ garmin_rd_deinit(void) static void garmin_txt_read(void) { - char buff[1024]; + char *buff; + textfile_t *tin; current_line = 0; + tin = textfile_init(fin); - while ((fgets(buff, sizeof(buff), fin))) { + while ((buff = textfile_read(tin))) { char *cin; current_line++; @@ -1253,6 +1255,7 @@ garmin_txt_read(void) /* flush pending data */ while (csv_lineparse(NULL, "\t", "", 0)); } + textfile_done(tin); } ff_vecs_t garmin_txt_vecs = { diff --git a/google.c b/google.c index 8e1872fac..6ff6a8f59 100644 --- a/google.c +++ b/google.c @@ -345,7 +345,6 @@ google_read(void) } } xfree( script ); - script = NULL; } } #endif @@ -355,8 +354,6 @@ google_rd_deinit(void) { xml_deinit(); mkshort_del_handle(&desc_handle); - encoded_points = NULL; - encoded_levels = NULL; } ff_vecs_t google_vecs = { diff --git a/gpsutil.c b/gpsutil.c index 9b108ad78..9881b7d9b 100644 --- a/gpsutil.c +++ b/gpsutil.c @@ -30,7 +30,7 @@ static short_handle mkshort_handle; static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); } static void @@ -56,7 +56,7 @@ wr_deinit(void) static void data_read(void) { - char ibuf[100]; + char *ibuf; char name[9], desc[31]; double lat,lon; char latdir, londir; @@ -65,17 +65,20 @@ data_read(void) char alttype; char icon[3] = {0}; waypoint *wpt_tmp; + textfile_t *tin; + + tin = textfile_init(file_in); /* * Make sure that all waypoints in single read have same * timestamp. */ time_t now = current_time(); - - for(;fgets(ibuf, sizeof(ibuf), file_in);) { + while ((ibuf = textfile_read(tin))) { /* A sharp in column zero or an blank line is a comment */ - if (ibuf[0] == '#' || ibuf[0] == '\n') continue; - sscanf(ibuf, "%s %le%c %le%c %ld%c %30[^,] %c", + ibuf = lrtrim(ibuf); + if (ibuf[0] == '#' || ibuf[0] == '\n') continue; + sscanf(ibuf, "%s %le%c %le%c %ld%c %30[^,] %c", name, &lat, &latdir, &lon, &londir, &alt, &alttype, desc, icon); desc[0] = '\0'; @@ -102,6 +105,7 @@ data_read(void) wpt_tmp->icon_descr = mag_find_descr_from_token(icon); waypt_add(wpt_tmp); } + textfile_done(tin); } static void diff --git a/hsa_ndv.c b/hsa_ndv.c index 18abb53ee..58a41e1cd 100644 --- a/hsa_ndv.c +++ b/hsa_ndv.c @@ -247,7 +247,7 @@ hsa_ndv_read(void) } if (!XML_Parse(psr, buf, len, feof(fd))) { fatal(MYNAME ":Parse error at %d: %s\n", - XML_GetCurrentLineNumber(psr), + (int) XML_GetCurrentLineNumber(psr), XML_ErrorString(XML_GetErrorCode(psr))); } } diff --git a/igc.c b/igc.c index 0ff3e96ac..693027042 100644 --- a/igc.c +++ b/igc.c @@ -26,11 +26,11 @@ #include "defs.h" #include -static FILE *file_in; static FILE *file_out; static char manufacturer[4]; static const route_head *head; static char *timeadj = NULL; +static textfile_t* tin; #define MYNAME "IGC" #define MAXRECLEN 79 // Includes null terminator and CR/LF @@ -88,42 +88,37 @@ static unsigned char coords_match(double lat1, double lon1, double lat2, double * @param rec Caller allocated storage for the record. At least MAXRECLEN chars must be allocated. * @return the record type. rec_none on EOF, rec_bad on fgets() or parse error. */ -static igc_rec_type_t get_record(char *rec) +static igc_rec_type_t get_record(char **rec) { size_t len; + char *c; - if (fgets(rec, MAXRECLEN, file_in) == NULL) { - if (feof(file_in)) { - return rec_none; - } else { - warning(MYNAME " fgets(): %s\n", strerror(errno)); - return rec_bad; - } - } - len = strlen(rec); - if (len < 3 || rec[0] < 'A' || rec[0] > 'Z') { - warning(MYNAME " bad input record: '%s'\n", rec); + *rec = c = textfile_read(tin); + if (c == NULL) return rec_none; + + len = strlen(c); + if (len < 3 || c[0] < 'A' || c[0] > 'Z') { + warning(MYNAME " bad input record: '%s'\n", c); return rec_bad; } - rec[len - 2] = '\0'; - return (igc_rec_type_t) rec[0]; + return (igc_rec_type_t) c[0]; } static void rd_init(const char *fname) { - char ibuf[MAXRECLEN]; + char *ibuf; - file_in = xfopen(fname, "rb", MYNAME); + tin = textfile_open_read(fname, MYNAME); // File must begin with a manufacturer/ID record - if (get_record(ibuf) != rec_manuf_id || sscanf(ibuf, "A%3[A-Z]", manufacturer) != 1) { + if (get_record(&ibuf) != rec_manuf_id || sscanf(ibuf, "A%3[A-Z]", manufacturer) != 1) { fatal(MYNAME ": %s is not an IGC file\n", fname); } } static void rd_deinit(void) { - fclose(file_in); + textfile_done(tin); } /** @@ -240,7 +235,7 @@ static void igc_task_rec(const char *rec) static void data_read(void) { - char ibuf[MAXRECLEN]; + char *ibuf; igc_rec_type_t rec_type; unsigned int hours, mins, secs; unsigned int lat_deg, lat_min, lat_frac; @@ -266,7 +261,7 @@ static void data_read(void) strcpy(trk_desc, HDRMAGIC HDRDELIM); while (1) { - rec_type = get_record(ibuf); + rec_type = get_record(&ibuf); switch (rec_type) { case rec_manuf_id: // Manufacturer/ID record already found in rd_init(). diff --git a/inifile.c b/inifile.c index 8b2b26d9f..5dd2b025f 100644 --- a/inifile.c +++ b/inifile.c @@ -73,7 +73,7 @@ try_open_gpsbabel_inifile(const char *path) /* can be empty or NULL */ #endif } strcat(buff, GPSBABEL_INIFILE); - result = fopen(buff, "r"); + result = fopen(buff, "rb"); xfree(buff); return result; @@ -87,7 +87,7 @@ open_gpsbabel_inifile(void) envstr = getenv("GPSBABELINI"); if (envstr != NULL) { - res = fopen(envstr, "r"); + res = fopen(envstr, "rb"); if (res == NULL) { warning("WARNING: GPSBabel-inifile, defined in environment, NOT found!\n"); return NULL; @@ -121,24 +121,15 @@ static void inifile_load_file(FILE *fin, inifile_t *inifile, const char *myname) { char *buf; - size_t bufsize = START_BUFSIZE; inifile_section_t *sec = NULL; + textfile_t *tin; - buf = xmalloc(bufsize); + tin = textfile_init(fin); - while ((fgets(buf, bufsize, fin))) + while ((buf = textfile_read(tin))) { - char *cin; - - while (strchr(buf, '\n') == NULL) - { - buf = xrealloc(buf, bufsize + DELTA_BUFSIZE); - cin = fgets(buf + bufsize - 1, DELTA_BUFSIZE + 1, fin); - bufsize+=DELTA_BUFSIZE; - if (cin == NULL) break; - } + char *cin = lrtrim(buf); - cin = lrtrim(buf); if (*cin == '\0') continue; /* skip empty lines */ if ((*cin == '#') || (*cin == ';')) continue; /* skip comments */ @@ -192,7 +183,7 @@ inifile_load_file(FILE *fin, inifile_t *inifile, const char *myname) entry->val = xstrdup(""); } } - xfree(buf); + textfile_done(tin); } static char * @@ -243,7 +234,7 @@ inifile_init(const char *filename, const char *myname) fin = open_gpsbabel_inifile(); if (fin == NULL) return NULL; } - else fin = xfopen(filename, "r", myname); + else fin = xfopen(filename, "rb", myname); result = xcalloc(1, sizeof(*result)); QUEUE_INIT(&result->secs); diff --git a/netstumbler.c b/netstumbler.c index ded3c2c5b..ad7cf6068 100644 --- a/netstumbler.c +++ b/netstumbler.c @@ -54,7 +54,7 @@ arglist_t netstumbler_args[] = { static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); macstumbler = 0; } @@ -67,7 +67,7 @@ rd_deinit(void) static void data_read(void) { - char ibuf[512]; + char *ibuf; char ssid[2 + 32 + 2 + 1]; /* "( " + SSID + " )" + null */ char mac[2 + 17 + 2 + 1]; /* "( " + MAC + " )" + null */ char desc[sizeof ssid - 1 + 15 + 1]; /* room for channel/speed */ @@ -78,13 +78,16 @@ data_read(void) long flags = 0; int speed = 0, channel = 0; struct tm tm; - + textfile_t *tin; + + tin = textfile_init(file_in); memset(&tm, 0, sizeof(tm)); - for(; fgets(ibuf, sizeof(ibuf), file_in);) { + while ((ibuf = textfile_read(tin))) { char *field; int field_num, len, i, stealth = 0; + ibuf = lrtrim(ibuf); /* A sharp in column zero might be a comment. Or it might be * something useful, like the date. */ @@ -221,7 +224,7 @@ data_read(void) waypt_add(wpt_tmp); } - + textfile_done(tin); fix_netstumbler_dupes(); } diff --git a/nmea.c b/nmea.c index 51573143a..f2b6f6fcb 100644 --- a/nmea.c +++ b/nmea.c @@ -200,7 +200,7 @@ nmea_rd_init(const char *fname) { curr_waypt = NULL; last_waypt = NULL; - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); } static void @@ -708,9 +708,10 @@ nmea_parse_one_line(char *ibuf) static void nmea_read(void) { - char ibuf[1024]; + char *ibuf; char *ck; double lt = -1; + textfile_t *tin; posn_type = gp_unknown; trk_head = NULL; @@ -730,8 +731,9 @@ nmea_read(void) } curr_waypt = NULL; + tin = textfile_init(file_in); - while (fgets(ibuf, sizeof(ibuf), file_in)) { + while ((ibuf = textfile_read(tin))) { nmea_parse_one_line(ibuf); if (lt < last_read_time && curr_waypt && trk_head) { if (curr_waypt != last_waypt) { @@ -744,6 +746,8 @@ nmea_read(void) /* try to complete date-less trackpoints */ nmea_fix_timestamps(trk_head); + + textfile_done(tin); } diff --git a/nmn4.c b/nmn4.c index cd5ec473e..fea273a55 100644 --- a/nmn4.c +++ b/nmn4.c @@ -97,20 +97,6 @@ nmn4_concat(char *arg0, ...) return res; } -static char * -nmn4_read_line(char *buff, size_t buffsize, FILE *fin) -{ - char *res; - - while ((res = fgets(buff, buffsize, fin))) - { - res = lrtrim(res); - if (*res == '\0') continue; - return res; - } - return NULL; -} - static void nmn4_check_line(char *line) { @@ -128,19 +114,24 @@ nmn4_check_line(char *line) static void nmn4_read_data(void) { - char buff[1024]; + char *buff; char *str, *c; int column; char *zip1, *zip2, *city, *street, *number; route_head *route; waypoint *wpt; + textfile_t *tin; route = route_head_alloc(); route_add_head(route); - while ((str = nmn4_read_line(buff, sizeof(buff), fin))) + tin = textfile_init(fin); + while ((buff = textfile_read(tin))) { + str = buff = lrtrim(buff); + if (*buff == '\0') continue; + nmn4_check_line(buff); /* for a quiet compiler */ @@ -235,6 +226,7 @@ nmn4_read_data(void) } route_add_wpt(route, wpt); } + textfile_done(tin); } static void @@ -299,7 +291,7 @@ nmn4_write_data(void) static void nmn4_rd_init(const char *fname) { - fin = xfopen(fname, "r", MYNAME); + fin = xfopen(fname, "rb", MYNAME); fin_name = xstrdup(fname); } diff --git a/ozi.c b/ozi.c index 985b34250..e90c50927 100644 --- a/ozi.c +++ b/ozi.c @@ -310,7 +310,7 @@ ozi_route_pr() static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); mkshort_handle = mkshort_new_handle(); } @@ -577,16 +577,17 @@ ozi_parse_routeheader(int field, char *str, waypoint * wpt_tmp) static void data_read(void) { - char buff[1024]; + char *buff; char *s; waypoint *wpt_tmp; int i; int linecount = 0; + textfile_t *tin; + + tin = textfile_init(file_in); - do { + while ((buff = textfile_read(tin))) { linecount++; - memset(buff, '\0', sizeof(buff)); - fgets(buff, sizeof(buff), file_in); /* * this is particularly nasty. use the first line of the file @@ -669,7 +670,8 @@ data_read(void) /* empty line */ } - } while (!feof(file_in)); + } + textfile_done(tin); } static void diff --git a/pcx.c b/pcx.c index 72100e111..2d6b5764d 100644 --- a/pcx.c +++ b/pcx.c @@ -48,7 +48,7 @@ arglist_t pcx_args[] = { static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); } static void @@ -85,16 +85,18 @@ data_read(void) char time[9]; char month[4]; waypoint *wpt_tmp; - char buff[122]; + char *buff; struct tm tm; route_head *track = NULL; route_head *route = NULL; int n; char lathemi, lonhemi; + textfile_t *tin; read_as_degrees = 0; + tin = textfile_init(file_in); - for(;fgets(buff, sizeof(buff), file_in);) + while ((buff = textfile_read(tin))) { char *ibuf = lrtrim(buff); char *cp; @@ -215,6 +217,7 @@ data_read(void) ; } } + textfile_done(tin); } static void diff --git a/polygon.c b/polygon.c index 7b0eeacd5..462c14c11 100644 --- a/polygon.c +++ b/polygon.c @@ -195,17 +195,16 @@ polygon_process(void) int fileline = 0; int first = 1; int last = 0; + char *line; + textfile_t *tin; - FILE *polyfile = xfopen( polyfileopt, "r", MYNAME ); + tin = textfile_open_read(polyfileopt, MYNAME ); olat = olon = lat1 = lon1 = lat2 = lon2 = BADVAL; - while ( !feof(polyfile)) { - char line[200]; + while ((line = textfile_read(tin))) { char *pound = NULL; int argsfound = 0; - fgets( line, sizeof(line), polyfile ); - fileline++; pound = strchr( line, '#' ); @@ -268,9 +267,7 @@ polygon_process(void) lon1 = lon2; } } - - fclose(polyfile); - + textfile_done(tin); QUEUE_FOR_EACH(&waypt_head, elem, tmp) { waypoint *wp = (waypoint *) elem; diff --git a/stmwpp.c b/stmwpp.c index 7dc1fda14..4a765f0a7 100644 --- a/stmwpp.c +++ b/stmwpp.c @@ -56,7 +56,7 @@ arglist_t stmwpp_args[] = static void stmwpp_rd_init(const char *fname) { - fin = xfopen(fname, "r", MYNAME); + fin = xfopen(fname, "rb", MYNAME); track = NULL; route = NULL; wpt = NULL; @@ -71,15 +71,19 @@ stmwpp_rd_deinit(void) static void stmwpp_data_read(void) { - char buff[1024]; + char *buff; + textfile_t *tin; + + tin = textfile_init(fin); what = STM_NOTHING; - fgets(buff, sizeof(buff), fin); + buff = textfile_read(tin); + buff = (buff == NULL) ? "" : buff; if (strncmp(buff, "Datum,WGS 84,WGS 84,", 20) != 0) fatal(MYNAME ": Invalid GPS datum or not \"WaypointPlus\"\" file!\n"); - while (fgets(buff, sizeof(buff), fin) != NULL) + while ((buff = textfile_read(tin))) { char *c; int column = -1; @@ -177,6 +181,7 @@ stmwpp_data_read(void) wpt = NULL; } } + textfile_done(tin); } static void diff --git a/textfile.c b/textfile.c new file mode 100644 index 000000000..a500c9fef --- /dev/null +++ b/textfile.c @@ -0,0 +1,124 @@ +/* + Utilities for reading textfiles. + + Copyright (C) 2006 Olaf Klein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ +#include "defs.h" + +textfile_t * +textfile_init(const FILE *file_in) +{ + textfile_t *res; + + res = xcalloc(1, sizeof(*res)); + + res->file_in = (FILE *)file_in; + res->buf_pos = res->buf_end = res->buf; + res->line = xstrdup(""); + + return res; +} + +textfile_t * +textfile_open_read(const char *filename, const char *module) +{ + textfile_t *tf; + + tf = textfile_init(xfopen(filename, "rb", module)); + tf->tfclose = 1; + return tf; +} + +int +textfile_getc(textfile_t *tf) +{ + int res; + + if (tf->buf_pos == tf->buf_end) { + int bytes; + + tf->buf_pos = tf->buf_end = tf->buf; + bytes = fread(tf->buf, 1, sizeof(tf->buf), tf->file_in); + tf->buf_end += bytes; + + if (bytes == 0) { + *tf->buf_pos = 0x1a; + tf->buf_end++; + return EOF; + } + } + res = *tf->buf_pos; + if (res == 0x1a) return EOF; + else { + tf->buf_pos++; + return res; + } +} + +unsigned char +textfile_eof(textfile_t *tf) +{ + int ch = textfile_getc(tf); + + if (ch == EOF) return 1; + else { + tf->buf_pos--; + return 0; + } +} + +char *textfile_read(textfile_t *tf) +{ + int len = 0; + char *res = tf->line; + + tf->line_no++; + + while (1) { + int c = textfile_getc(tf); + + if ((c == EOF) || (c == 0x1a)) { + if (len == 0) return NULL; + else break; + } + else if (c == '\r') { + c = textfile_getc(tf); + if (c != '\n') tf->buf_pos--; + break; + } + else if (c == '\n') { + break; + } + if (len == tf->line_size) { + tf->line_size+=128; + res = tf->line = xrealloc(tf->line, tf->line_size + 1); + } + res[len] = c; + len++; + } + res[len] = '\0'; + return res; +} + +void +textfile_done(textfile_t *tf) +{ + xfree(tf->line); + if (tf->tfclose) fclose(tf->file_in); + xfree(tf); +} diff --git a/tiger.c b/tiger.c index ab0953d82..d97511e6d 100644 --- a/tiger.c +++ b/tiger.c @@ -99,7 +99,7 @@ arglist_t tiger_args[] = { static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); mkshort_handle = mkshort_new_handle(); } @@ -129,10 +129,13 @@ data_read(void) double lat,lon; char desc[100]; char icon[100]; - char ibuf[1024]; + char *ibuf; waypoint *wpt_tmp; + textfile_t *tin; - while (fgets(ibuf, sizeof(ibuf), file_in)) { + tin = textfile_init(file_in); + + while ((ibuf = textfile_read(tin))) { if( sscanf(ibuf, "%lf,%lf:%100[^:]:%100[^\n]", &lon, &lat, icon, desc)) { wpt_tmp = waypt_new(); @@ -145,6 +148,7 @@ data_read(void) waypt_add(wpt_tmp); } } + textfile_done(tin); } static void diff --git a/tmpro.c b/tmpro.c index 73c23e738..a0b3018db 100644 --- a/tmpro.c +++ b/tmpro.c @@ -45,7 +45,7 @@ static short_handle mkshort_handle; static void rd_init(const char *fname) { - file_in = xfopen(fname, "r", MYNAME); + file_in = xfopen(fname, "rb", MYNAME); } static void @@ -69,17 +69,18 @@ wr_deinit(void) static void data_read(void) { - char buff[1024]; + char *buff; char *s; char *holder; waypoint *wpt_tmp; int i; int linecount = 0; - - do { + textfile_t *tin; + + tin = textfile_init(file_in); + + while ((buff = textfile_read(tin))) { linecount++; - memset(&buff, '\0', sizeof(buff)); - fgets(buff, sizeof(buff), file_in); /* skip the line if it contains "sHyperLink" as it is a header (I hope :) */ if ((strlen(buff)) && (strstr(buff, "sHyperLink") == NULL)) { @@ -170,7 +171,8 @@ data_read(void) /* empty line */ } - } while (!feof(file_in)); + } + textfile_done(tin); } static void diff --git a/unicsv.c b/unicsv.c index 1deddd8e3..a5de55a4d 100644 --- a/unicsv.c +++ b/unicsv.c @@ -25,6 +25,7 @@ #define MYNAME "unicsv" static FILE *fin; +static textfile_t *tin; /* This structure must contain only ints. Firstval must be first. * This is block initialized. @@ -55,11 +56,11 @@ arglist_t unicsv_args[] = { /* fread_buff: returns only left and right trimmed non-empty lines or NULL */ static char * -fread_buff(char *buff, const size_t buff_size, FILE *fin) +fread_buff(textfile_t *tin) { char *result; - while ((result = fgets(buff, buff_size, fin))) + while ((result = textfile_read(tin))) { result = lrtrim(result); if (*result != '\0') break; @@ -139,13 +140,14 @@ unicsv_fondle_header(char *ibuf) static void unicsv_rd_init(const char *fname) { - char ibuf[1024]; + char *c; unicsv_altscale = 1.0; - fin = xfopen(fname, "r", MYNAME); + fin = xfopen(fname, "rb", MYNAME); + tin = textfile_init(fin); - if (NULL != fread_buff(ibuf, sizeof(ibuf), fin)) - unicsv_fondle_header(ibuf); + if ((c = textfile_read(tin))) + unicsv_fondle_header(c); else unicsv_fieldsep = NULL; } @@ -153,8 +155,8 @@ unicsv_rd_init(const char *fname) static void unicsv_rd_deinit(void) { + textfile_done(tin); fclose(fin); - fin = NULL; } static void @@ -214,12 +216,14 @@ unicsv_parse_one_line(char *ibuf) static void unicsv_rd(void) { - char buff[1024]; + char *buff; if (unicsv_fieldsep == NULL) return; - while (fread_buff(buff, sizeof(buff), fin)) { - unicsv_parse_one_line(buff); + while ((buff = textfile_read(tin))) { + buff = lrtrim(buff); + if (*buff) + unicsv_parse_one_line(buff); } } diff --git a/xcsv.c b/xcsv.c index 1b6d114a2..64a4ff34e 100644 --- a/xcsv.c +++ b/xcsv.c @@ -440,17 +440,17 @@ xcsv_parse_style_buff(const char *sbuff) static void xcsv_read_style(const char *fname) { - char sbuff[8192]; + char *sbuff; FILE *fp; + textfile_t *tin; xcsv_file_init(); - fp = xfopen(fname, "r", MYNAME); + fp = xfopen(fname, "rb", MYNAME); + tin = textfile_init(fp); - do { - memset(sbuff, '\0', sizeof(sbuff)); - fgets(sbuff, sizeof(sbuff), fp); - rtrim(sbuff); + while ((sbuff = textfile_read(tin))) { + sbuff = lrtrim(sbuff); xcsv_parse_style_line(sbuff); } while (!feof(fp)); @@ -461,7 +461,7 @@ xcsv_read_style(const char *fname) xcsv_file.ofield = &xcsv_file.ifield; xcsv_file.ofield_ct = xcsv_file.ifield_ct; } - + textfile_done(tin); fclose(fp); } -- 2.30.2